Advanced Usage¶
This notebook covers advanced patterns and customization options.
In [1]:
Copied!
import numpy as np
import pandas as pd
import xarray as xr
from xarray_plotly import config, xpx
config.notebook() # Configure Plotly for notebook rendering
import numpy as np
import pandas as pd
import xarray as xr
from xarray_plotly import config, xpx
config.notebook() # Configure Plotly for notebook rendering
Working with xarray Attributes¶
xarray_plotly automatically uses metadata from xarray attributes for labels:
In [2]:
Copied!
da = xr.DataArray(
np.random.randn(30, 3).cumsum(axis=0) + 15,
dims=["time", "station"],
coords={
"time": pd.date_range("2024-01-01", periods=30, freq="D"),
"station": ["Alpine", "Coastal", "Urban"],
},
name="temperature",
attrs={
"long_name": "Air Temperature",
"units": "°C",
"standard_name": "air_temperature",
},
)
# Add coordinate attributes
da.coords["time"].attrs = {"long_name": "Time", "units": "days"}
da.coords["station"].attrs = {"long_name": "Measurement Station"}
# Labels are automatically extracted from attrs
fig = xpx(da).line(title="Temperature with Auto-Labels")
fig
da = xr.DataArray(
np.random.randn(30, 3).cumsum(axis=0) + 15,
dims=["time", "station"],
coords={
"time": pd.date_range("2024-01-01", periods=30, freq="D"),
"station": ["Alpine", "Coastal", "Urban"],
},
name="temperature",
attrs={
"long_name": "Air Temperature",
"units": "°C",
"standard_name": "air_temperature",
},
)
# Add coordinate attributes
da.coords["time"].attrs = {"long_name": "Time", "units": "days"}
da.coords["station"].attrs = {"long_name": "Measurement Station"}
# Labels are automatically extracted from attrs
fig = xpx(da).line(title="Temperature with Auto-Labels")
fig
Configuring Label Behavior¶
Use config.set_options() to control how labels are extracted from attributes:
In [3]:
Copied!
# Disable units in labels
with config.set_options(label_include_units=False):
fig = xpx(da).line(title="Without Units in Labels")
fig
# Disable units in labels
with config.set_options(label_include_units=False):
fig = xpx(da).line(title="Without Units in Labels")
fig
Overriding Labels¶
You can override the automatic labels:
In [4]:
Copied!
fig = xpx(da).line(
labels={
"temperature": "Temp (°C)",
"time": "Date",
"station": "Location",
},
title="Custom Labels",
)
fig
fig = xpx(da).line(
labels={
"temperature": "Temp (°C)",
"time": "Date",
"station": "Location",
},
title="Custom Labels",
)
fig
In [5]:
Copied!
np.random.seed(42)
da_complex = xr.DataArray(
np.random.randn(20, 3, 2, 2),
dims=["time", "city", "scenario", "model"],
coords={
"time": pd.date_range("2024-01-01", periods=20),
"city": ["NYC", "LA", "Chicago"],
"scenario": ["SSP2", "SSP5"],
"model": ["GCM-A", "GCM-B"],
},
name="projection",
)
# Use line_dash for one dimension, color for another
fig = xpx(da_complex.sel(city="NYC")).line(
color="scenario",
line_dash="model",
title="Multiple Visual Encodings",
)
fig
np.random.seed(42)
da_complex = xr.DataArray(
np.random.randn(20, 3, 2, 2),
dims=["time", "city", "scenario", "model"],
coords={
"time": pd.date_range("2024-01-01", periods=20),
"city": ["NYC", "LA", "Chicago"],
"scenario": ["SSP2", "SSP5"],
"model": ["GCM-A", "GCM-B"],
},
name="projection",
)
# Use line_dash for one dimension, color for another
fig = xpx(da_complex.sel(city="NYC")).line(
color="scenario",
line_dash="model",
title="Multiple Visual Encodings",
)
fig
Reducing Dimensions Before Plotting¶
When you have more dimensions than slots, reduce them first:
In [6]:
Copied!
# Average over model dimension
fig = xpx(da_complex.mean("model")).line(
facet_col="city",
title="Ensemble Mean by City",
)
fig
# Average over model dimension
fig = xpx(da_complex.mean("model")).line(
facet_col="city",
title="Ensemble Mean by City",
)
fig
In [7]:
Copied!
# Select a specific slice
fig = xpx(da_complex.sel(scenario="SSP5", model="GCM-A")).line(
facet_col="city",
title="SSP5 / GCM-A Projections",
)
fig
# Select a specific slice
fig = xpx(da_complex.sel(scenario="SSP5", model="GCM-A")).line(
facet_col="city",
title="SSP5 / GCM-A Projections",
)
fig
Custom Styling¶
Themes¶
In [8]:
Copied!
da_simple = da.sel(station="Urban")
fig = xpx(da_simple).line(
template="plotly_dark",
title="Dark Theme",
)
fig
da_simple = da.sel(station="Urban")
fig = xpx(da_simple).line(
template="plotly_dark",
title="Dark Theme",
)
fig
Custom Colors¶
In [9]:
Copied!
import plotly.express as px
fig = xpx(da).line(
color_discrete_sequence=px.colors.qualitative.Set2,
title="Custom Color Palette",
)
fig
import plotly.express as px
fig = xpx(da).line(
color_discrete_sequence=px.colors.qualitative.Set2,
title="Custom Color Palette",
)
fig
Heatmap Colorscales¶
In [10]:
Copied!
da_2d = xr.DataArray(
np.random.randn(20, 30),
dims=["lat", "lon"],
name="anomaly",
)
# Diverging colorscale centered at zero
fig = xpx(da_2d).imshow(
color_continuous_scale="RdBu_r",
color_continuous_midpoint=0,
title="Diverging Colorscale",
)
fig
da_2d = xr.DataArray(
np.random.randn(20, 30),
dims=["lat", "lon"],
name="anomaly",
)
# Diverging colorscale centered at zero
fig = xpx(da_2d).imshow(
color_continuous_scale="RdBu_r",
color_continuous_midpoint=0,
title="Diverging Colorscale",
)
fig
Post-Creation Customization¶
All plots return Plotly Figure objects that can be extensively customized:
In [11]:
Copied!
fig = xpx(da).line()
# Add horizontal reference line
fig.add_hline(y=15, line_dash="dash", line_color="gray", annotation_text="Reference")
# Update layout
fig.update_layout(
title="Temperature with Reference Line",
legend={"orientation": "h", "yanchor": "bottom", "y": 1.02, "xanchor": "right", "x": 1},
)
fig
fig = xpx(da).line()
# Add horizontal reference line
fig.add_hline(y=15, line_dash="dash", line_color="gray", annotation_text="Reference")
# Update layout
fig.update_layout(
title="Temperature with Reference Line",
legend={"orientation": "h", "yanchor": "bottom", "y": 1.02, "xanchor": "right", "x": 1},
)
fig
Modifying Traces¶
In [12]:
Copied!
fig = xpx(da).line()
# Make all lines thicker
fig.update_traces(line_width=3)
fig.update_layout(title="Thicker Lines")
fig
fig = xpx(da).line()
# Make all lines thicker
fig.update_traces(line_width=3)
fig.update_layout(title="Thicker Lines")
fig
Exporting Figures¶
Integration Examples¶
With xarray operations¶
In [13]:
Copied!
# Rolling mean
da_smooth = da.rolling(time=7, center=True).mean()
fig = xpx(da_smooth).line(
title="7-Day Rolling Mean",
)
fig
# Rolling mean
da_smooth = da.rolling(time=7, center=True).mean()
fig = xpx(da_smooth).line(
title="7-Day Rolling Mean",
)
fig
In [14]:
Copied!
# Groupby operations
da_monthly = xr.DataArray(
np.random.randn(365, 3).cumsum(axis=0),
dims=["time", "category"],
coords={
"time": pd.date_range("2024-01-01", periods=365),
"category": ["A", "B", "C"],
},
name="value",
)
monthly_mean = da_monthly.groupby("time.month").mean()
fig = xpx(monthly_mean).line(
title="Monthly Climatology",
)
fig.update_xaxes(
tickmode="array",
tickvals=list(range(1, 13)),
ticktext=["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
)
fig
# Groupby operations
da_monthly = xr.DataArray(
np.random.randn(365, 3).cumsum(axis=0),
dims=["time", "category"],
coords={
"time": pd.date_range("2024-01-01", periods=365),
"category": ["A", "B", "C"],
},
name="value",
)
monthly_mean = da_monthly.groupby("time.month").mean()
fig = xpx(monthly_mean).line(
title="Monthly Climatology",
)
fig.update_xaxes(
tickmode="array",
tickvals=list(range(1, 13)),
ticktext=["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
)
fig